﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using _2013_ece_csharp_snake;
using System.Diagnostics;

public class Snake
{
    private Point head;         // position of snake head
    private Point dir;          // direction of head
    private Point size;         // size of snke square
    private IList<Point> body;  // all pos of all body points
    private int speed;          // speed of snake
    private int lenght;
    private DataSend data;
    private Panel panel;

    public Point Head {
        get { return head; }
    }

    public Snake(Panel panel)
    {
        this.panel = panel;

        speed = panel.Height / 60;
        lenght = 1;

        size.X = panel.Height / 14;
        size.Y = panel.Height / 14;

        body = new List<Point>();
        body.Add(new Point(100,100));

        head.X = 10 + panel.Left;
        head.Y = 10 + panel.Top;
        dir.X = speed;
        dir.Y = 0;


        data = new DataSend(head.X - panel.Left, head.Y - panel.Top);
    }

    public void grow()
    {
        lenght++;
        body.Add(new Point());
    }

    public void actuPos()
    {
        Point temp1;
        Point temp2;

        for (int i = lenght-1; i > 0; i--)
        {
            temp1 = body[i];
            temp2 = body[i - 1];
            if ( ! (temp1.X == temp2.X && temp1.Y == temp2.Y) )
                body[i] = body[i - 1];
        }

        body[0] = head;

        head.X += dir.X;
        head.Y += dir.Y;
    }

    public void prepareDataSend()
    {
        data.headX = (double)(this.head.X - panel.Left) / panel.Width;
        data.headY = (double)(this.head.Y - panel.Top) / panel.Height;

        IList<PointF> b = data.body;

        //for (int i = 0; i < body.Count; i++)
        for (int i = 0; i < 1; i++)
        {
            if (i >= b.Count)
                b.Add(new PointF((float)(this.body[i].X - panel.Left) / panel.Width,
                                 (float)(this.body[i].Y - panel.Top) / panel.Height));
            else
            {
                PointF temp = new PointF((float)(this.body[i].X - panel.Left) / panel.Width,
                                         (float)(this.body[i].Y - panel.Top) / panel.Height);

                b[i] = temp;
            }
        }
    }

    public void handleDataReceived()
    {

        this.head.X = (int)Convert.ToInt32(data.headX * panel.Width) + panel.Left;
        this.head.Y = (int)Convert.ToInt32(data.headY * panel.Height) + panel.Top;

        IList<PointF> b = data.body;

        for (int i = 0; i < b.Count; i++)
        {
            if (i >= body.Count)
                body.Add(new Point());

            Point temp = new Point((int)Convert.ToInt32(b[i].X * panel.Width) + panel.Left,
                                   (int)Convert.ToInt32(b[i].Y * panel.Height) + panel.Top);
            body[i] = temp;
        }

    }

    public void goUp()
    {
        dir.X = 0;
        dir.Y = -speed;
    }

    public void goDown()
    {
        dir.X = 0;
        dir.Y = speed;
    }

    public void goRight()
    {
        dir.X = speed;
        dir.Y = 0;
    }

    public void goLeft()
    {
        dir.X = -speed;
        dir.Y = 0;
    }

    public void checkWall(int topWall, int bottomWall, int leftWall, int rightWall)
    {
        // if colision with the wall on the right
        if ((head.X - size.X/2) > rightWall && dir.X > 0)
            head.X = leftWall - size.X/2;
        // if colision with the wall on the left
        if ((head.X + size.X/2 + 5) < leftWall && dir.X < 0)
            head.X = rightWall + Size.X/2;
        // if colision with the wall on the top
        if ((head.Y + size.Y/2) < topWall && dir.Y < 0)
            head.Y = bottomWall + size.Y/2;
        // if colision with the wall on the bottom
        if ((head.Y - size.Y/2) > bottomWall && dir.Y > 0)
            head.Y = topWall - (size.Y/2);
    }

    public IList<Point> Body
    {
        get { return body; }
        set { body = value; }
    }

    public Point Size
    {
        get { return size; }
        set { size = value; }
    }

    public int Lenght
    {
        get { return lenght; }
        set { lenght = value; }
    }

    public Point Dir
    {
        get { return dir; }
        set { dir = value; }
    }

    internal DataSend Data
    {
        get { return data; }
        set { data = value; }
    }
}
